#!/usr/bin/env python

import gtk
from gtk import gdk
import math

import cairo
import numpy
import csv
import sys

import goocanvas

class PyApp(gtk.Window):

    def __init__(self):

        # Seismic header keywords
        dt = 4000
        dx = 1

        super(PyApp, self).__init__()

        self.set_title("Seismic Data")
        self.resize(500, 500)
        self.set_position(gtk.WIN_POS_CENTER)

        self.connect("destroy", gtk.main_quit)

        # Creating the canvas
        self.canvas = goocanvas.Canvas ()
        self.canvas.set_flags (gtk.CAN_FOCUS)
        self.canvas.set_bounds (0, 0, 500, 500)
        self.root = self.canvas.get_root_item() 

        # Adding the seismic image
        print "Loading Data..."
        self.pb = gtk.gdk.pixbuf_new_from_file('example.png')
        x,y = self.canvas.get_bounds()[2:4];
        w = self.pb.get_width ()
        h = self.pb.get_height ()
        self.image = goocanvas.Image(pixbuf=self.pb,parent=self.root, 
                                x=0, y=0,
                                width=w, height=h) 


        scale_x = float(x) / float(w)

        if h < y:
            scale_y = float(h) / float(y)
        else:
            scale_y =  float(y) / float(h)

        self.image.scale(scale_x, scale_y)

        # Picks array
        self.picks = []

        # Vbox to put the canvas inside
        vbox = gtk.VBox()
        vbox.pack_start (self.canvas, True, True, 0)

        # Create a table for placing the ruler and the canvas
        table = gtk.Table(3, 2, False)
        self.add(table)

        table.attach(vbox, 1, 2, 1, 2,
                     gtk.EXPAND|gtk.FILL, gtk.FILL, 0, 0 )
        vbox.set_events(gtk.gdk.POINTER_MOTION_MASK |
                        gtk.gdk.POINTER_MOTION_HINT_MASK )

        # The horizontal ruler goes on top. As the mouse moves across the
        # drawing area, a motion_notify_event is passed to the
        # appropriate event handler for the ruler.
        self.hrule = gtk.HRuler()
        self.hrule.set_metric(gtk.PIXELS)

        self.hrule_max_x = float(dx * w)
        self.hrule.set_range(0, self.hrule_max_x, 0, self.hrule_max_x)

        table.attach(self.hrule, 1, 2, 0, 1,
                     gtk.EXPAND|gtk.SHRINK|gtk.FILL, gtk.FILL, 0, 0 )
    
        # The vertical ruler goes on the left. As the mouse moves across
        # the drawing area, a motion_notify_event is passed to the
        # appropriate event handler for the ruler.
        self.vrule = gtk.VRuler()
        self.vrule.set_metric(gtk.PIXELS)

        self.vrule_max_y = float(dt * h / 1e+06)
        self.vrule.set_range(0, self.vrule_max_y, 0, self.vrule_max_y)
        table.attach(self.vrule, 0, 1, 1, 2,
                     gtk.FILL, gtk.EXPAND|gtk.SHRINK|gtk.FILL, 0, 0 )


        self.show_all()

        # Connecting the events
        # Auto scaling the canvas and seismic image
        def motion_notify(widget, event):
            x, y, _ = self.canvas.window.get_pointer()
            w = self.canvas.get_allocation()[2]
            h = self.canvas.get_allocation()[3]
            min = self.hrule.get_range()[0]
            max = self.hrule.get_range()[1]
            x = float(x)/float(w)
            x *= (max - min) 
            x += min
            self.hrule.props.position = x

            min = self.vrule.get_range()[0]
            max = self.vrule.get_range()[1]
            y = float(y)/float(h)
            y *= (max - min) 
            y += min
            self.vrule.props.position = y

            return True



        vbox.connect("motion-notify-event", motion_notify)
        vbox.connect("size-allocate", self.do_configure_event)
        self.root.connect ("button-press-event", self.canvas_event)
        self.root.connect ("button-release-event", self.canvas_event)
        self.root.connect ("scroll-event", self.canvas_event)
        self.root.connect_after("motion-notify-event", self.canvas_event)
        self.root.connect("key-press-event", self.canvas_event)
        self.canvas.grab_focus(self.root)
        self.dragging = False
        self.selected_items = []

    def canvas_event (self, item, target, event):
        # Creates a rubberband on left-click
        if (event.type == gtk.gdk.BUTTON_PRESS):
            self.canvas.grab_focus(self.root)
            if (event.button == 1):
                self.dragging = True
                self.startx = event.x
                self.starty = event.y
                self.rubberband = goocanvas.Polyline (parent = self.root,
                                fill_color_rgba = 0x3cb37180)
                return True

            if (event.button == 3):
                self.popup_menu (item, target, event)
                return True

        # Updates the rubberband size while a mouse drags
        if (event.type == gtk.gdk.MOTION_NOTIFY) and (self.dragging):
            x0, y0 = self.canvas.convert_from_item_space(self.image, self.startx, self.starty)
            x1, y1 = self.canvas.convert_from_item_space(self.image, event.x, event.y)
            points = goocanvas.Points([(x0, y0), (x0,y1), (x1, y1), (x1, y0), (x0, y0)])
            self.rubberband.props.points = points

            return True

        # Destroys the rubberband and sends selection data to the relevant method
        if (event.type == gtk.gdk.BUTTON_RELEASE):
            if (event.button == 1 and self.dragging):
                    self.dragging = False
                    self.endx = event.x
                    self.endy = event.y
                    if self.startx == self.endx and self.starty == self.endy:
                        print "button-release"
                        self.create_pick (item, target, event)
                        return True

            x0, y0 = self.canvas.convert_from_item_space(self.image, self.startx, self.starty)
            x1, y1 = self.canvas.convert_from_item_space(self.image, event.x, event.y)
            if x1 >= x0:
                if y1 >= y0:
                    area = goocanvas.Bounds(x0, y0, x1, y1)
                else:
                    area = goocanvas.Bounds(x0, y1, x1, y0)
            else:
                if y1 >= y0:
                    area = goocanvas.Bounds(x1, y0, x0, y1)
                else:
                    area = goocanvas.Bounds(x1, y1, x0, y0)

            self.selected_items = self.canvas.get_items_in_area(area, True, False, False)
            if self.selected_items != None:
                for pick in self.picks:
                    pick.props.fill_color = "blue"
                for item in self.selected_items:
                    item.props.fill_color = "red"
            self.rubberband.remove()

        if (event.type == gtk.gdk.KEY_PRESS):
            print "key-press"
            if gtk.gdk.keyval_name(event.keyval) == "Delete" and self.selected_items != None:
                print "Deletar pick"
                for item in self.selected_items:
                    item.remove()

    def popup_menu (self, item, target, event):
        menu = gtk.Menu()
        select_item = gtk.MenuItem("Rubber Band Selection")
        zoom_item = gtk.MenuItem("Rubber Band Zoom")
        quit_item = gtk.MenuItem("Quit")

        menu.append(select_item)
        menu.append(zoom_item)
        menu.append(quit_item)

        quit_item.connect("activate", gtk.main_quit)

        select_item.show()
        zoom_item.show()
        quit_item.show()
        menu.popup(None, None, None, event.button, event.time, None)

        return True

    def change_zoom (self, item, target, event):
        scale = self.canvas.get_scale()

        if event.direction == gdk.SCROLL_UP: 
            scale += 0.05
            self.canvas.set_scale(scale)
        else: 
            scale -= 0.05
            if scale <= 1.0:
                scale = 1.0
            self.canvas.set_scale(scale)

        return True 

    def create_pick (self, item, target, event):

        if event.button != 1:
            return False

        x, y = self.canvas.convert_from_item_space(self.image, event.x, event.y)

        item = goocanvas.Rect (parent = self.root,
                               x = x - 5,
                               y = y - 5,
                               width = 10,
                               height = 10,
                               stroke_pattern = None,
                               fill_color = "blue",
                               line_width = 5.0,
                               can_focus = True)

        item.connect ("focus_in_event", self.on_focus_in)
        item.connect ("focus_out_event", self.on_focus_out)
        item.connect ("button_press_event", self.on_button_press)
        item.connect ("key_press_event",  self.on_key_press)

        self.picks.append(item)

        return True

    def on_key_press (self, item, target, event):
        if gtk.gdk.keyval_name(event.keyval) == "Delete":
            print "Deletar pick"
            item.remove()

        return False

    def on_focus_in (self, item, target, event):
        item.props.fill_color = "red"

        return False

    def on_focus_out (self, item, target, event):
        item.props.fill_color = "blue" 

        return False

    def on_button_press (self, item, target, event):
        canvas = item.get_canvas ()
        canvas.grab_focus (item)

        return True

    def do_configure_event(self,widget, event):
        x,y = self.canvas.get_bounds()[2:4];

        rect = widget.get_allocation() 
        self.canvas.set_bounds(0,0,rect.width,rect.height) 
        self.image.width = rect.width
        self.image.height = rect.height

        if x == rect.width:
            scale_x = 1.0
        else:
            if  x < rect.width:
                scale_x = (rect.width - x) / x
                scale_x += 1.0
            else:
                scale_x = (x - rect.width) / x
                scale_x = 1.0 - scale_x
        
        if y == rect.height:
            scale_y = 1.0
        else:
            if  y < rect.height:
                scale_y = (rect.height - y) / y
                scale_y += 1.0
            else:
                scale_y = (y - rect.height) / y
                scale_y = 1.0 - scale_y


        for pick in self.picks:
                pick.props.x = pick.props.x * scale_x
                pick.props.y = pick.props.y * scale_y
                
        self.image.scale(scale_x, scale_y)


PyApp()
gtk.main()

